/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/


#include <stdio.h>
#include <malloc.h>

#include "bitestream.h"



int prevpos = 0;

void p(BiteStream *s) {
    int i;

    if (prevpos == 0) {
        printf("Stream has %d bytes:", s->length);
    }
    else {
        printf("Stream gained %d bytes:", s->length-prevpos);
    }

    for (i = prevpos; i < s->length; i++) {
        printf((i-prevpos) % 4 == 0 ? " %02x" : "%02x", (unsigned char) s->buf[i]);
        if (i-prevpos >= 20) {
            printf("...");
            break;
        }
    }
    
    printf("\n");
    
    prevpos = s->length;
}



int main(int argc, char **argv) {
    int foo[] = { 0xaabbccdd, 0xeeff0011, 0x22334455, 0x66778899 };
    BiteStream *s, *d;
    bsTag *t;
    char *mem = malloc(1048576);
    int i;

    s = bsAlloc();
    p(s);

    printf("Adding an int\n");
    bsAddInt(s, 100, 0x87654321);
    p(s);

    printf("Adding a float\n");
    bsAddFloat(s, 101, 12.3);
    p(s);

    printf("Adding a double\n");
    bsAddDouble(s, 102, 12.3);
    p(s);

    printf("Adding a string\n");
    bsAddStr(s, 103, "Herro, wolrd!");
    p(s);

    printf("Adding another string\n");
    bsAddStr(s, 135841, "BiTE");
    p(s);

    printf("Adding binary data\n");
    bsAddBin(s, 16000000, &foo, 16);
    p(s);


    printf("Adding a kilobyte of data\n");
    bsAddBin(s, 1024, mem, 1024);
    p(s);

    printf("Adding a megabyte of data\n");
    bsAddBin(s, 1025, mem, 1048576);
    p(s);

    printf("Adding an int\n");
    bsAddInt(s, 200, 12345678);
    p(s);


    printf("Adding an empty string\n");
    bsAddStr(s, 256, "");
    p(s);

    printf("Adding a 1-char string\n");
    bsAddStr(s, 257, "x");
    p(s);

    printf("Adding a 3-char string\n");
    bsAddStr(s, 258, "abc");
    p(s);


    printf("Adding a named string tag\n");
    bsAddNamedStr(s, "foo", "bar");
    p(s);
    
    printf("Adding a final integer to check integrity\n");
    bsAddInt(s, 666, 0);
    p(s);


    printf("Finalizing stream\n");
    bsFinalize(s);
    p(s);

    // prints a hexdump of the whole stream (just the beginning)
    printf("\n");
    prevpos = 0;
    p(s);

    // start reading the stream now
    printf("\nDecoding stream:\n");
    d = bsDecode(s->buf);
    printf("Stream has %d tags and %d bytes.\n", d->numtags, d->length);

    while ((t = bsNextTag(d))) {
        if (t->name) {
            printf("Found tag \"%s\", length %d", t->name, t->length);
        }
        else {
            printf("Found tag %d, length %d", t->tag, t->length);
        }
        switch (t->tag) {
            case 103:
            case 135841:
            case 256:
            case 257:
            case 258:
            case BS_NAMED:
                printf(": \"%s\"", t->string);
                break;
                
            default:
                if (t->length == 4) {
                    printf(", value could be %d ", t->value);
                    if (t->value < 0) {
                        printf("or %u ", t->value);
                    }
                    printf("or %.1f", *(float *) t->data);
                }
        }
        printf("\n");

    }
    printf("Stream ended.\n");

    bsFree(d);
    
    printf("\nClearing stream buffer\n\n");
    bsClear(s);
    
    prevpos = 0;
    p(s);
    
    printf("Adding ints\n");
    for (i = 0; i < 20; i++) {
        bsAddInt(s, 500+i, i);
    }
    p(s);
    
    printf("Finalizing stream\n");
    bsFinalize(s);
    p(s);

    // prints a hexdump of the whole stream (just the beginning)
    printf("\n");
    prevpos = 0;
    p(s);



    bsFree(s);

    return 0;
}



